package com.mlming.simpledb.backend.dm;

import com.mlming.simpledb.backend.dm.dataItem.DataItem;
import com.mlming.simpledb.backend.dm.logger.Logger;
import com.mlming.simpledb.backend.dm.page.PageOneDataHandler;
import com.mlming.simpledb.backend.dm.pageCache.PageCache;
import com.mlming.simpledb.backend.tm.TransactionManager;

public interface DataManager {
    DataItem read(int pgno, short offset) throws Exception; // 从pgno对应的页的offset位置读取出DataItem
    long insert(long xid, byte[] data) throws Exception; // xid对应的事务 要往 数据库中插入data数据
    void close();

    // 在指定路径上创建db文件, 并以此创建PageCache实例
    // 在指定路径上创建log文件, 并以此创建Logger实例
    // 创建DataManagerImpl实例, 同时初始化db文件的第一页
    public static DataManager create(String path, long mem, TransactionManager tm) {
        PageCache pc = PageCache.create(path, mem);
        Logger lg = Logger.create(path);
        DataManagerImpl dm = new DataManagerImpl(pc, lg, tm);
        dm.initPageOne();
        return dm;
    }

    // 通过指定路径上的db文件, 创建PageCache实例
    // 通过指定路径上的log文件, 创建Logger实例
    // 创建DataManagerImpl实例
    // 检验db文件中的第一页的正确性, 如果不正确, 说明之前数据库非正常关闭了, 所以要调用Recover进行崩溃恢复
    // 此时db文件里可能是有页面数据的, 所以要调用fillPageIndex()来加载到页面索引中去
    public static DataManager open(String path, long mem, TransactionManager tm) {
        PageCache pc = PageCache.open(path, mem);
        Logger lg = Logger.open(path);
        DataManagerImpl dm = new DataManagerImpl(pc, lg, tm);
        if(!dm.loadCheckPageOne()) {
            Recover.recover(tm, lg, pc);
        }
        dm.fillPageIndex();
        // 重新再写入随机字符串,用于下一次的验证
        PageOneDataHandler.setVcOpen(dm.pageOne);
        // 把修改后的第一页刷盘到db文件中
        dm.pc.flushPage(dm.pageOne);
        return dm;
    }
}
